//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#include <QSignalMapper>
#include <QAction>
#include "actiondispatcher.h"
//
class ActionDispatcher::DefaultHandler:public ActionState
{
public:
   DefaultHandler(ActionDispatcher *disp,QAction *action);
protected:
   void force_detach();
};
//
ActionDispatcher::DefaultHandler::DefaultHandler(ActionDispatcher *disp,QAction *action)
:
   ActionState(disp,action,disp)
{
   action->setEnabled(false);
   action->setChecked(false);
}
void ActionDispatcher::DefaultHandler::force_detach()
{
   ActionState::force_detach();
   delete this;
}
//
//
//
ActionDispatcher::ActionDispatcher(QObject *parent)
:
   QObject(parent)
{
}
ActionDispatcher::~ActionDispatcher()
{
   for(HandlerHash::iterator itr=handler.begin();itr!=handler.end();++itr)
   {
      HandlerList &handlers=itr.value();
      for(int i=0;i<handlers.size();++i)
         handlers.at(i)->force_detach();
   }
   handler.clear();
}
//
void ActionDispatcher::triggered(bool checked)
{
   QAction * const action=qobject_cast<QAction*>(sender());
   HandlerHash::iterator const hand=handler.find(action);
   if(hand!=handler.end())
   {
      Q_ASSERT(hand.value().front()->get_enabled());
      hand.value().front()->emit_triggered(checked);
   }
}
//
void ActionDispatcher::register_action(QAction *action)
{
   if(!handler.contains(action))
   {
      handler.insert(action,HandlerList());
      new DefaultHandler(this,action);
      connect(action,SIGNAL(triggered(bool)),this,SLOT(triggered(bool)));
   }
}
void ActionDispatcher::unregister_action(QAction *action)
{
   if(handler.contains(action))
   {
      const HandlerList &handlers=handler.value(action);
      for(int i=0;i<handlers.size();++i)
         handlers.at(i)->force_detach();
      handler.remove(action);
      disconnect(action,SIGNAL(triggered(bool)),this,SLOT(triggered(bool)));
   }
}
//
void ActionDispatcher::attach_handler(ActionState& state)
{
   Q_ASSERT(handler.contains(state.action));
   HandlerList &handlers=handler[state.action];
   if(!handlers.contains(&state))
   {
      handlers.append(&state);
   }
}
void ActionDispatcher::detach_handler(ActionState& state)
{
   Q_ASSERT(handler.contains(state.action));
   HandlerList &handlers=handler[state.action];
   if(handlers.front()==&state)
   {
      state.set_inactive();
      handlers.pop_front();
      handlers.front()->set_active();
   }
   else
   {
      handlers.removeAll(&state);
   }
}
void ActionDispatcher::activate_handler(ActionState &state)
{
   Q_ASSERT(handler.contains(state.action));
   HandlerList &handlers=handler[state.action];
   int const i=handlers.indexOf(&state);
   Q_ASSERT(i!=-1);
   if(i>0)
   {
      handlers.front()->set_inactive();
      handlers.move(i,0);
      handlers.front()->set_active();
   }
}
void ActionDispatcher::deactivate_handler(ActionState &state)
{
   Q_ASSERT(handler.contains(state.action));
   HandlerList &handlers=handler[state.action];
   int const i=handlers.indexOf(&state);
   Q_ASSERT(i!=-1);
   if(i==0)
   {
      handlers.front()->set_inactive();
      handlers.move(i,handlers.length()-1);
      handlers.front()->set_active();
   }
}
